package com.freework.freedbm.dao.jdbcm.map.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.freework.freedbm.base.BaseDTO;
import com.freework.freedbm.cfg.tablecfg.TableQuery;
import com.freework.freedbm.dao.DefaultProtoQueryDAO;
import com.freework.freedbm.dao.DefaultProtoUpdateDAO;
import com.freework.freedbm.dao.jdbcm.Param;
import com.freework.freedbm.dao.jdbcm.QueryInfo;
import com.freework.freedbm.dao.jdbcm.QueryManager;
import com.freework.freedbm.dao.jdbcm.map.dto.MapDTOUtil;
import com.freework.freedbm.dao.jdbcm.map.dto.MapDTO;
import com.freework.freedbm.dao.jdbcm.map.dto.MapDTOCfg;
import com.freework.freedbm.util.DTOByCfg;

@Transactional
@Service
public class MapDaoSupport extends NamedParameterJdbcDaoSupport  {

	@Resource(name = "dataSource")
	public void setSuperDataSource(DataSource dataSource) {
		this.setDataSource(dataSource);
		MapDTOUtil.setDaoSupport(this);
	}
	protected DefaultProtoQueryDAO qdao = DefaultProtoQueryDAO.getDefaultQueryDAO();

	protected DefaultProtoUpdateDAO udao = DefaultProtoUpdateDAO.getDefaultUpdateDAO();
	protected QueryManager jdbcManager=QueryManager.getJdbcManager();
	
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public List<Map> query(final String tableName,final String where) {
		return (List<Map>) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						MapDTOCfg tablecfg=	MapDTOUtil.getTableInfo(conn, tableName);
						QueryInfo qi = QueryInfo.getQueryInfo(tablecfg, where);
						return qdao.query(conn, qi);
					}
				});
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public List<Map> query(final String sql,final Param... paramsArgs) {
		return (List<Map>) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						
						PreparedStatement preparedStatement = null;
						ResultSet resultSet = null;
						List list = new ArrayList();
						try {
							preparedStatement =jdbcManager. getQueryPreparedStatement(sql,false, conn);
							if(paramsArgs.length!=0){
								List<Param> params=Arrays.asList(paramsArgs);
	
								if(params!=null)
									jdbcManager.setPreparedStatement(params,preparedStatement);
							}
							resultSet = preparedStatement.executeQuery();
							Object rdto = null;
							TableQuery newdto=MapDTOUtil.getQueryInfo(resultSet.getMetaData(), sql);
							while (resultSet.next()) {
								rdto =  newdto.newInstance();
								jdbcManager.setResultSetValue(newdto.getFields(), rdto, resultSet);
								list.add(rdto);
							}
						} catch (SQLException e) {
							throw e;
						} finally {
							jdbcManager.close(resultSet, preparedStatement);
						}
						return list;
					}
				});
	}
	
	
	
	
	
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public List<Map> queryPage(final int start, final int limit,final String tableName,final String where) {
		return (List<Map>) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						MapDTOCfg tablecfg=	MapDTOUtil.getTableInfo(conn, tableName);
						QueryInfo qi = QueryInfo.getQueryInfo(tablecfg, where);
						qi.setStart(start);
						qi.setLimit(limit);
						return qdao.query(conn, qi);
					}
				});
	}
	
	public MapDTOCfg  getMapDTOCfg(String tableName){
		Connection conn=null;
		try {
			conn=getDataSource().getConnection();
			 MapDTOCfg tablecfg=MapDTOUtil.getTableInfo(conn, tableName);
			 return tablecfg;

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}finally{
			if(conn!=null)
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
	
	
	public int insertByKey(final MapDTO dto) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						return udao.insertByKey(dto, conn);
					}
				});
	} 

	public int insertByKey(final Map map,final String tableName) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						BaseDTO dto=MapDTOUtil.mapToDto(conn, tableName,map);
						return udao.insertByKey(dto, conn);
					}
				});
	} 

	public int insert(final Map map,final String tableName) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						BaseDTO dto=MapDTOUtil.mapToDto(conn, tableName,map);
						return udao.insert(dto, conn);
					}
				});
	} 
	public int insert(final MapDTO dto) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						return udao.insert(dto, conn);
					}
				});
	} 
	public int updateAll(final MapDTO dto) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						return udao.updateAll(dto, conn);
					}
				});
	} 
	public int updateAll(final Map map,final String tableName) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						BaseDTO dto=MapDTOUtil.mapToDto(conn, tableName,map);

						return udao.updateAll(dto, conn);
					}
				});
	} 
	public int update(final Map map,final String tableName) {
		return (Integer) super.getJdbcTemplate().execute(
				new ConnectionCallback() {
					public Object doInConnection(Connection conn)
							throws SQLException {
						BaseDTO dto=MapDTOUtil.mapToUpdateDto(conn, tableName,map);
						if(DTOByCfg.getUpdateField(dto,false).length!=0)
							return udao.update(dto, conn);
						else
							return 0;
					}
				});
	} 

}
